﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SFWS.XHandler.Core;
using System.Linq.Expressions;
using System.Reflection;

namespace JKF.Substructure
{
    public static class UrlActionManger
    {
        /// <summary>
        /// 用表达式树的方式,执行方法,并按照参数名称从Requset取得值
        /// 方法的参数支持简单类型,但是可能出现string无法转换int的情况,所以参数类型最好是string类型
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="ActionName"></param>
        public static void Manager(this AHttpHandler handler, string ActionName)
        {
            MethodInfo methodInfo = handler.GetType().GetMethod(ActionName);
            if (methodInfo == null)
            {
                throw new Exception("没有找到public 方法");
            }
            ParameterExpression instanceParameter =
                Expression.Parameter(typeof(object), "instance");
            ParameterExpression parametersParameter =
                Expression.Parameter(typeof(object[]), "parameters");
            // build parameter list
            List<Expression> parameterExpressions = new List<Expression>();
            ParameterInfo[] paramInfos = methodInfo.GetParameters();
            var parsVal = new List<object>();
            for (int i = 0; i < paramInfos.Length; i++)
            {
                // (Ti)parameters[i]
                BinaryExpression valueObj = Expression.ArrayIndex(
                    parametersParameter, Expression.Constant(i));
                UnaryExpression valueCast = Expression.Convert(
                    valueObj, paramInfos[i].ParameterType);
                var str = handler.Context.Request[paramInfos[i].Name] ?? string.Empty;
                try
                {
                    parsVal.Add(Convert.ChangeType(str.Trim(), paramInfos[i].ParameterType));
                }
                catch
                {
                    parsVal.Add(null);
                }

                parameterExpressions.Add(valueCast);
            }
            // (TInstance)instance
            Expression instanceCast = Expression.Convert(instanceParameter, methodInfo.ReflectedType);

            // static invoke or ((TInstance)instance).Method
            MethodCallExpression methodCall = Expression.Call(
                instanceCast, methodInfo, parameterExpressions);

            Expression<Action<AHttpHandler, object[]>> lambda =
                    Expression.Lambda<Action<AHttpHandler, object[]>>(
                        methodCall, instanceParameter, parametersParameter);

            Action<AHttpHandler, object[]> execute = lambda.Compile();
            execute(handler, parsVal.ToArray());
        }

        /// <summary>
        /// 支持复杂对象参数
        /// </summary>
        /// <param name="t"></param>
        public static void Manager(Type t)
        {
            var m = t.GetMethod(Utils.GetActionName);
            var o = Activator.CreateInstance(t);

            var tt = m.GetParameters();
            var obj = new object[tt.Length];
            for (var i = 0; i < tt.Length; i++)
            {
                var parameterInfo = tt[i];
                var tType = parameterInfo.ParameterType;
                var jname = parameterInfo.Name;
                var a = System.Web.HttpContext.Current.Request[jname].Trim();

                if (tType.Equals(typeof(string)) || (!tType.IsInterface && !tType.IsClass))
                {
                    try
                    {
                        //改变参数类型   
                        obj[i] = Convert.ChangeType(a, tType);
                    }
                    catch
                    {
                        //改变参数类型   
                        obj[i] = null;
                    }


                }
                else if (tType.IsClass) //如果是类,将它的json字符串转换成对象   
                {
                    obj[i] = Newtonsoft.Json.JsonConvert.DeserializeObject(a, tType);

                }
            }

            m.Invoke(o, obj);


        }
    }
}
